﻿using Newtonsoft.Json;
using System;
using System.CodeDom;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Web;
using System.Web.Services.Description;
using System.Xml.Serialization;

namespace Brc_DSB.WebService.WebServiceHelper
{
    public class WebServiceCall
    {
        private string _serviceAddress;
        public WebServiceCall(string serviceAddress)
        {
            _serviceAddress = serviceAddress;
        }
        public T Invoke<T>(string className, string methodName, object[] paramters)
        {
            WebClient web = new WebClient();
            System.Web.Services.Description.ServiceDescription description = null;
            using (Stream stream = web.OpenRead(_serviceAddress))
            {
                description = ServiceDescription.Read(stream);
            }
            //创建客户端代理
            var agent = CreateClientAgent(description);
            //编译客户端代理
            var compileResult = AgentCodeCompile(agent);
            if (compileResult.Errors.HasErrors)
            {
                throw new Exception("编译错误");
            }
            Assembly asm = compileResult.CompiledAssembly;
            Type t = asm.GetType(className);
            object o = Activator.CreateInstance(t);
            MethodInfo method = t.GetMethod(methodName);
            var invokeResult = method.Invoke(o, paramters);
            T result = JsonConvert.DeserializeObject<T>(JsonConvert.SerializeObject(invokeResult));
            return result;
        }
        /// <summary>
        /// 创建客户端代理类
        /// </summary>
        /// <param name="description"></param>
        /// <returns></returns>
        private ServiceDescriptionImporter CreateClientAgent(ServiceDescription description)
        {
            ServiceDescriptionImporter importer = new ServiceDescriptionImporter();
            importer.ProtocolName = "Soap";
            importer.Style = ServiceDescriptionImportStyle.Client;
            importer.CodeGenerationOptions = CodeGenerationOptions.GenerateProperties | CodeGenerationOptions.GenerateNewAsync;
            importer.AddServiceDescription(description, null, null);
            return importer;
        }

        private CompilerResults AgentCodeCompile(ServiceDescriptionImporter agent)
        {
            CodeNamespace nmspace = new CodeNamespace();
            CodeCompileUnit unit = new CodeCompileUnit();
            unit.Namespaces.Add(nmspace);
            ServiceDescriptionImportWarnings warning = agent.Import(nmspace, unit);
            using (CodeDomProvider provider = CodeDomProvider.CreateProvider("CSharp"))
            {
                CompilerParameters parameter = new CompilerParameters();
                parameter.GenerateExecutable = false;
                parameter.GenerateInMemory = true;
                parameter.ReferencedAssemblies.Add("System.dll");
                parameter.ReferencedAssemblies.Add("System.XML.dll");
                parameter.ReferencedAssemblies.Add("System.Web.Services.dll");
                parameter.ReferencedAssemblies.Add("System.Data.dll");
                return provider.CompileAssemblyFromDom(parameter, unit);
            }
        }
    }
}